#!/bin/sh /etc/rc.common
#
# Copyright (C) 2015 OpenWrt-dist
#
# This is free software, licensed under the GNU General Public License v3.
# See /LICENSE for more information.
#

START=30

CONFIG=mia
UTCTZ="0"

uci_export_section_name() {
  local ret=$(uci -n export $CONFIG | grep "config $1" | awk '{print $3}' | awk -F\' '{print $2}')
  echo ${ret:=$2}
}
uci_get_by_name() {
	local ret=$(uci get $CONFIG.$1.$2 2>/dev/null)
	echo ${ret:=$3}
}
uci_get_by_type() {
	local index=0
	if [ -n "$4" ]; then
		index=$4
	fi
	local ret=$(uci get $CONFIG.@$1[$index].$2 2>/dev/null)
	echo ${ret:=$3}
}
uci_get_mac_by_template(){
  local ret=""
  for i in $(seq 0 100)
  do
    local enable=$(uci_get_by_type macbind enable '' $i)
    local macaddr=$(uci_get_by_type macbind macaddr '' $i)
    local template=$(uci_get_by_type macbind template '' $i)
    if [ -z $enable ] || [ -z $macaddr ] || [ -z $template ]; then
      break
    fi
    if [ "$enable" == "1" ]; then
      if [ -z "$1" ] || [ "$template" == "$1" ]; then
        if [ "$ret" == "" ]; then
          ret=$macaddr
        else
          ret="$ret $macaddr"
        fi
      fi
    fi
  done
  echo ${ret:=$2}
}
#result "-1/0/1 **:**-**:**/0 [**:**-**:**]"
#first param -1/0/1 -1=minus one day 0=current day 1=add one day
#second param from time to time or 0=no time, when first param is -1, the time minus one day ...
#third param from time to time, when first param is 1, the time add one day ...
convert_time_on_off(){
  local tz=$(date +%z | sed -E 's/(.)(..)(..)/\1 \2 \3/')
  local flag=""
  local timeon=$1
  local timeonoff=$2
  local ret="0 $1-$2"
  for t in $tz
  do
    if [ "$t" == "00" ]; then
      continue
    fi
    if [ "$t" == "+" ]; then
      flag="-"
    elif [ "$t" == "-" ]; then
      flag="+"
    else
      houron=$(echo $timeon | awk -F: '{print $1}')
      minon=$(echo $timeon | awk -F: '{print $2}')
      houroff=$(echo $timeonoff | awk -F: '{print $1}')
      minoff=$(echo $timeonoff | awk -F: '{print $2}')
      if [ "$flag" == "+" ]; then
        houron_utc=`expr $houron + $t`
        if [ "$houron_utc" -gt 23 ]; then
          houron_utc=`expr $houron_utc - 24`
          houroff_utc=`expr $houroff + $t - 24`
          ret="1 0 $houron_utc:$minon-$houroff_utc:$minoff"
        else
          houroff_utc=`expr $houroff + $t`
          if [ "$houroff_utc" -gt 23 ]; then
            houroff_utc=`expr $houroff_utc - 24`
            ret="1 $houron_utc:$minon-23:59 00:00-$houroff_utc:$minoff"
          else
            ret="0 $houron_utc:$minon-$houroff_utc:$minoff"
          fi
        fi
      elif [ "$flag" == "-" ]; then
        if [ "$houroff" -lt "$t" ]; then
          houron_utc=`expr $houron - $t + 24`
          houroff_utc=`expr $houroff - $t + 24`
          ret="-1 $houron_utc:$minon-$houroff_utc:$minoff"
        else
          if [ "$houron" -lt "$t" ]; then
            houron_utc=`expr $houron - $t + 24`
            houroff_utc=`expr $houroff - $t`
            ret="-1 $houron_utc:$minon-23:59 00:00-$houroff_utc:$minoff"
          else
            houron_utc=`expr $houron - $t`
            houroff_utc=`expr $houroff - $t`
            ret="0 $houron_utc:$minon-$houroff_utc:$minoff"
          fi
        fi
      fi
    fi
  done
  echo ${ret:=$3}
}
convert_weekdays(){
  local z1="0"
  local z2="0"
  local z3="0"
  local z4="0"
  local z5="0"
  local z6="0"
  local z7="0"
  Z1=""
  Z2=""
  Z3=""
  Z4=""
  Z5=""
  Z6=""
  Z7=""
  if [ "$9" == "-1" ]; then
    if [ "$1" == "1" ]; then
      z7=$1
    fi
    if [ "$2" == "1" ]; then
      z1=$2
    fi
    if [ "$3" == "1" ]; then
      z2=$3
    fi
    if [ "$4" == "1" ]; then
      z3=$4
    fi
    if [ "$5" == "1" ]; then
      z4=$5
    fi
    if [ "$6" == "1" ]; then
      z5=$6
    fi
    if [ "$7" == "1" ]; then
      z6=$7
    fi
  elif [ "$9" == "1" ]; then
    if [ "$1" == "1" ]; then
      z2=$1
    fi
    if [ "$2" == "1" ]; then
      z3=$2
    fi
    if [ "$3" == "1" ]; then
      z4=$3
    fi
    if [ "$4" == "1" ]; then
      z5=$4
    fi
    if [ "$5" == "1" ]; then
      z6=$5
    fi
    if [ "$6" == "1" ]; then
      z7=$6
    fi
    if [ "$7" == "1" ]; then
      z1=$7
    fi
  else
    local z1=$1
    local z2=$2
    local z3=$3
    local z4=$4
    local z5=$5
    local z6=$6
    local z7=$7
  fi
  [ "$z1" == "1" ] && Z1="Mon,"
  [ "$z2" == "1" ] && Z2="Tue,"
  [ "$z3" == "1" ] && Z3="Wed,"
  [ "$z4" == "1" ] && Z4="Thu,"
  [ "$z5" == "1" ] && Z5="Fri,"
  [ "$z6" == "1" ] && Z6="Sat,"
  [ "$z7" == "1" ] && Z7="Sun"
  local ret=$Z1$Z2$Z3$Z4$Z5$Z6$Z7
  echo ${ret:=$8}
}
add_rules(){
  local sections=$(uci_export_section_name templates '')
  if [ -n "$sections" ]; then
    for s in $sections
    do
      local enable=$(uci_get_by_name $s enable '' $i)
      local title=$(uci_get_by_name $s title '' $i)
      if [ -z $enable ]; then
        break
      fi
      if [ "$enable" == "1" ]; then
        local macaddrs=$(uci_get_mac_by_template $s '')
        if [ -n "$macaddrs" ]; then
          add_rule $s $macaddrs
        fi
      fi
    done
  fi
}
add_rule(){
  for macaddr in $2
  do
    iptables -t filter -A MIAPLUS  -m mac --mac-source $macaddr -j DROP
  done
  for i in $(seq 0 100)
  do
    local enable=$(uci_get_by_type $1 enable '' $i)
    local timeon=$(uci_get_by_type $1 timeon '' $i)
    local timeoff=$(uci_get_by_type $1 timeoff '' $i)
    local z1=$(uci_get_by_type $1 z1 '' $i)
    local z2=$(uci_get_by_type $1 z2 '' $i)
    local z3=$(uci_get_by_type $1 z3 '' $i)
    local z4=$(uci_get_by_type $1 z4 '' $i)
    local z5=$(uci_get_by_type $1 z5 '' $i)
    local z6=$(uci_get_by_type $1 z6 '' $i)
    local z7=$(uci_get_by_type $1 z7 '' $i)
    [ "$z1" == "1" ] && Z1="Mon,"
    [ "$z2" == "1" ] && Z2="Tue,"
    [ "$z3" == "1" ] && Z3="Wed,"
    [ "$z4" == "1" ] && Z4="Thu,"
    [ "$z5" == "1" ] && Z5="Fri,"
    [ "$z6" == "1" ] && Z6="Sat,"
    [ "$z7" == "1" ] && Z7="Sun"

    if [ -z $enable ] || [ -z $timeoff ] || [ -z $timeon ]; then
      break
    fi
    if [ "$enable" == "1" ]; then
      for macaddr in $2
      do
        if [ $UTCTZ == "1" ]; then
          iptables -t filter -I MIAPLUS  -m mac --mac-source $macaddr -m time --kerneltz --timestart $timeon --timestop $timeoff --weekdays $Z1$Z2$Z3$Z4$Z5$Z6$Z7 -j ACCEPT
        else
          local timeutc=$(convert_time_on_off $timeon $timeoff '')
          local flag=$(echo $timeutc | awk -F ' ' '{print $1}')
          local t=$(echo $timeutc | awk -F ' ' '{print $2}')
          if [ "$t" != "0" ]; then
            local timeon=$(echo $t | awk -F- '{print $1}')
            local timeoff=$(echo $t | awk -F- '{print $2}')
            if [ "$flag" == "-1" ]; then
              local weekdays=$(convert_weekdays $z1 $z2 $z3 $z4 $z5 $z6 $z7 '' $flag)
              iptables -t filter -I MIAPLUS  -m mac --mac-source $macaddr -m time --kerneltz --timestart $timeon --timestop $timeoff --weekdays $weekdays -j ACCEPT
            else
              iptables -t filter -I MIAPLUS  -m mac --mac-source $macaddr -m time --kerneltz --timestart $timeon --timestop $timeoff --weekdays $Z1$Z2$Z3$Z4$Z5$Z6$Z7 -j ACCEPT
            fi
          fi
          t=$(echo $timeutc | awk -F ' ' '{print $3}')
          if [ -n "$t" ]; then
            local timeon=$(echo $t | awk -F- '{print $1}')
            local timeoff=$(echo $t | awk -F- '{print $2}')
            if [ "$flag" == "1" ]; then
              local weekdays=$(convert_weekdays $z1 $z2 $z3 $z4 $z5 $z6 $z7 '' $flag)
              iptables -t filter -I MIAPLUS  -m mac --mac-source $macaddr -m time --kerneltz --timestart $timeon --timestop $timeoff --weekdays $weekdays -j ACCEPT
            else
              iptables -t filter -I MIAPLUS  -m mac --mac-source $macaddr -m time --kerneltz --timestart $timeon --timestop $timeoff --weekdays $Z1$Z2$Z3$Z4$Z5$Z6$Z7 -j ACCEPT
            fi
          fi
        fi
      done
    fi
    for n in $(seq 1 7)
    do
      unset "Z$n"
    done
  done
}

del_rule(){
	type=$1
	blackMacAdd=$(iptables -t nat -L $type | grep -w RETURN | grep -w "MAC" | awk '{print $7}')
	[ -n "$blackMacAdd" ] && {
		for macaddrb in $blackMacAdd
		do
			iptables -t nat -D $type -m mac --mac-source $macaddrb -j RETURN
		done
	}
}

start(){
  stop
	enable=$(uci get mia.@basic[0].enable)
	[ $enable -eq 0 ] && exit 0
  iptables -t filter -N MIAPLUS
  iptables -I INPUT -p udp --dport 53 -m comment --comment "Rule For Control" -j MIAPLUS
  iptables -I INPUT -p tcp --dport 53 -m comment --comment "Rule For Control" -j MIAPLUS
  iptables -t nat -A PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 53 -m comment --comment "Rule For Control"
  iptables -t nat -A PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports 53 -m comment --comment "Rule For Control"
  strict=$(uci get mia.@basic[0].strict)
  [ $strict -eq 1 ] && iptables -t filter -I FORWARD -m comment --comment "Rule For Control" -j MIAPLUS
  UTCTZ=$(uci get mia.@basic[0].utctz)
  add_rules
}
stop(){
  iptables -t filter -D FORWARD -m comment --comment "Rule For Control" -j MIAPLUS 2>/dev/null
  iptables -D INPUT -p udp --dport 53 -m comment --comment "Rule For Control" -j MIAPLUS 2>/dev/null
  iptables -D INPUT -p tcp --dport 53 -m comment --comment "Rule For Control" -j MIAPLUS 2>/dev/null
  iptables -t nat -D PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 53 -m comment --comment "Rule For Control" 2>/dev/null
  iptables -t nat -D PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports 53 -m comment --comment "Rule For Control" 2>/dev/null
  iptables -t filter -F MIAPLUS 2>/dev/null
  iptables -t filter -X MIAPLUS 2>/dev/null
}
